//package ProjetoGeral.ParaAmbos;

//import ProjetoGeral.Servidor.ListaArquivos;
import java.net.*; // Para Socket, ServerSocket
import java.io.*; // Para IOException e Input/OutputStream

/**
 *
 * @author Larissa
 */
public final class TCPEchoServer implements Runnable{

	private static final int BUFSIZE = 32; // Tamanho do buffer de recepcao

        private Socket connection;
        private String TimeStamp;
        private int ID;
        private char comando;
        private String nodeOrigem;
        private String nodeDestino;
        private String nomeArquivo;
        private String mensagem;
        private String oQueInserirNoArquivo;
        
        public TCPEchoServer(){
            
        }
  
        private TCPEchoServer(Socket s, int i) throws IOException {
            this.connection = s;
            this.ID = i;     
        }
        
        public synchronized String buscaNo (String nomeArq){
        
        StringBuilder nodeArq = new StringBuilder();
        String linhaEncontrada = null;
        String nomeNode = null;
        int inicioNode = 0;
        int fimLinha = 0;
        int i = 0;
        int j = 0;
        int k = 0;
        char aux;
        
        
        try {
                String stringSearch = nomeArq;
                BufferedReader bf = new BufferedReader(new FileReader("ListaArquivos.txt"));
                int linecount = 0;
                String line;

                // Loop through each line, stashing the line into our line variable.
                while (( line = bf.readLine()) != null){
                   
                    linecount++;
                    int indexfound = line.indexOf(stringSearch);

                    // Se maior que -1, significa que encontramos o arquivo
                    if (indexfound > -1) {
                                           
                        while(indexfound != line.indexOf("#")){
                           aux = line.charAt(indexfound);
                           linhaEncontrada = nodeArq.append(aux).toString();
                           indexfound++;
                        }  
                        
                        indexfound = 0;
                        while(indexfound != line.indexOf("*")){
                           indexfound++;
                           inicioNode = indexfound;
                        }  
                        
                        indexfound = 0;
                        while(indexfound != line.indexOf("#")){
                           fimLinha = indexfound;
                           indexfound++;
                        }  
                        fimLinha = fimLinha+1;     
                        inicioNode = inicioNode + 1;
                    }                                  
               }            
                // Close the file after done searching
                bf.close();
            }
            catch (IOException e) {
                System.out.println("IO Error Occurred: " + e.toString());
            }
        return (linhaEncontrada.substring(inicioNode,fimLinha));
    }
        
        /*************** Manipulação da Lista de Arquivos *****************/
        
        public synchronized File criaArquivo(String nomeArq) throws IOException{
        
            File arquivo = new File(nomeArq);

            if(arquivo.exists() == false){
                arquivo.createNewFile();
                return(arquivo);
            }
            return null;
        }
        
        
        
        
        public synchronized void removeArquivo(String nomeArq) throws IOException{
         
            // Constroi um arquivo temporário
            File inputFile = new File("ListaArquivos.txt");
            File tempFile = new File(inputFile + "temp.txt");

            BufferedReader br = new BufferedReader (new FileReader("ListaArquivos.txt"));
            PrintWriter Pwr = new PrintWriter(new FileWriter (tempFile));
            String line = null;

            //read from original, write to temporary and trim space, while title not found
            while((line = br.readLine()) !=null) {
                if(line.trim().startsWith(nomeArq)){
                    continue;          }
                else{
                    Pwr.println(line);
                    Pwr.flush();

                }
            }
            // close readers and writers
            br.close();
            Pwr.close();

            // delete book file before renaming temp
            inputFile.delete();

            // rename temp file back to books.txt
            if(tempFile.renameTo(inputFile)){
                   System.out.println("Update succesful");
               }else{
                   System.out.println("Update failed");
               }
        }
        
        
        
        

        public synchronized void leArquivo (String nomeArq) throws IOException{

            try{
            //leitura
            BufferedReader br = new BufferedReader (new FileReader(nomeArq));

            //enquanto houver mais linhas
            while (br.ready()) {
                //lê a proxima linha
                String linha = br.readLine();
                //faz algo com a linha
                System.out.println(linha);
            }
            br.close();
            System.out.println("\nArquivo lido com sucesso!");
            }
            catch (IOException e) {
                System.out.println("exception occoured"+ e);
                System.out.println("Arquivo não existe.");
             }
        }
        
        
        
        
        
        
        
        
//PARA INSERIR OS NOMES DOS ARQUIVOS NA LISTA
       public synchronized void inserirArquivoNaLista(String nomeArquivo, String nodeOrigem) throws IOException{
            String texto = nomeArquivo+'*'+nodeOrigem+'#';
            escreveArquivo("ListaArquivos.txt", texto);
       }
       
       public synchronized void escreveArquivo (String nomeArq, String dado) throws IOException{

            try{
                //escreve no arquivo
                 BufferedWriter bw = new BufferedWriter(new FileWriter(nomeArq));
                 bw.append(dado);
                 bw.newLine();
                 bw.close();

                 System.out.println("\nEscrita feita com sucesso!");
            }
            catch (IOException e) {
                System.out.println("exception occoured"+ e);
                System.out.println("Arquivo não existe.");
             }
        }
        
        //Cria o arquivo da lista
        public synchronized File criaLista() throws IOException{
            File arquivo = new File("ListaArquivos.txt");
        
            if(arquivo.exists() == false){
                arquivo.createNewFile();
                return(arquivo);
            }
            return null;
        }

        //Cria a lista ListaArquivos.txt
        public synchronized void inicializarLista() throws IOException{
            int i;

            this.criaLista();
            
            System.out.println("Lista criada com sucesso!");
        }
        
        
        /************************************/
        
        public void tomarDecisao() throws IOException{
            if(this.comando == 'E'){
                        //comando para excluir da lista!! o this.oQueInserirNoArquivo;
                this.removeArquivo(this.nomeArquivo);
                
            }
            if(this.comando == 'M'){
                this.oQueInserirNoArquivo = this.nomeArquivo + '*' + this.nodeOrigem + '#';
            }
        }
        
        /************ Main ****************/
        
        public static void main(String[] args) throws IOException {
            int servPort = 9000;
            int count = 0;//Count serve para contar quantos sockets estao abertos.
            
            TCPEchoServer tcp = new TCPEchoServer();
            tcp.inicializarLista();
            
            try{
                System.out.println("Entrou!!!");
                ServerSocket socket1 = new ServerSocket(servPort);//Cria o socket na porta servPort
                System.out.println("Servidor pronto para aceitar múltiplas conexoes...");
                while (true) {
                      Socket connection = socket1.accept();//aceita a conexao
                      Runnable runnable = new TCPEchoServer(connection, ++count);//Aqui o socket vai incrementando conforme um socket é aberto
                      Thread thread = new Thread(runnable);
                      thread.start();
                }
            }
            catch (IOException e) {}
            
        }
        
        /*The run() method’s responsibility is to run the block of code that we want threaded.*/
        @Override
        public void run() {
                
            /*Esse código é só um exemplo, teremos que modificá-lo,
            porque aqui está tratando para string, nao sei como vamos fazer para arquivo.
            */
               try {
                    BufferedInputStream is = new BufferedInputStream(connection.getInputStream());
                    InputStreamReader isr = new InputStreamReader(is);//Para recepcao de dados
                    int character;
                    StringBuffer mensagemRecebida = new StringBuffer();
                    //Pega o nome do arquivo
                    while((character = isr.read()) != (int)'#') {//A '#' indica o final do nome do arquivo
                      mensagemRecebida.append((char)character);
                    }
                    this.mensagem = mensagemRecebida.toString();
                    int indice_final = this.retornarArquivoENode();
                    this.comando = this.mensagem.charAt(0);//pega o comando
                    this.nodeOrigem = this.mensagem.substring(1, indice_final);//pega o nó de origem
                    this.nomeArquivo = this.mensagem.substring(indice_final+1);//pega o nome do arquivo
                    System.out.println(this.nomeArquivo);
                    System.out.println(this.nomeArquivo + ',' + this.nodeOrigem);
                    //No caso de criacao de arquivo
                    if(this.comando == 'C'){
                        int character2;
                        //Vai receber outro nome de node - node em que será criado o arquivo
                        while((character2 = isr.read()) != (int)'#') { //A '#' indica o final do nome do arquivo
                            mensagemRecebida.append((char)character2);
                        }
                        
                        this.nodeDestino = mensagemRecebida.toString();
                        System.out.println("CRIAR:"+this.nodeDestino);
                        //Falta inserir no arquivo de ListaArquivos.txt o nome do arquivo e o sua localizacao
                        //Essa é a STRING que será inserida no arquivo
                        this.oQueInserirNoArquivo = this.nomeArquivo + '*' + this.nodeDestino + '#';
                        this.inserirArquivoNaLista(this.nomeArquivo, this.nodeDestino);
                    }else{
                        //Aqui ele só envia a posicao encontrada
                        try {
                          Thread.sleep(10000);
                        }
                        catch (InterruptedException e){}
                        
                        //Buscar aqui o arquivo na lista e retornar o seu destino
                        this.nodeDestino = this.buscaNo(this.nomeArquivo);
                        //this.nodeDestino = ;
                        BufferedOutputStream os = new BufferedOutputStream(connection.getOutputStream());//Para enviar dados..
                        OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII");
                        osw.write(this.nodeDestino+'#');//Enviando o dado...
                        osw.flush();
                        
                        this.oQueInserirNoArquivo = this.nomeArquivo + '*' + this.nodeDestino + '#';
//***********************************Ver o que vai ser feito com as outras possibilidades:E e M em relacao a lista
                        tomarDecisao();
                     }
               }
               catch (IOException e) {
                System.out.println(e);
               }
               finally {
                try {
                  connection.close();//Fecha a conexao.
                }
                catch (IOException e){}
               }
                      
        }
        
        public int retornarArquivoENode(){
            int i = 0;
            while(this.mensagem.charAt(i) != '*'){
                i++;
            }
            return (i);
        }
}

